/*
 * Copyright (c) 2006-2018, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author           Notes
 * 2020-09-06     heyuanjie87      the first version
 */

#include <board.h>
#include <rtdevice.h>
#include <rthw.h>

#define DCMI_D0_PIN (GPIO_PIN_6)
#define DCMI_D1_PIN (GPIO_PIN_7)
#define DCMI_D2_PIN (GPIO_PIN_0)
#define DCMI_D3_PIN (GPIO_PIN_1)
#define DCMI_D4_PIN (GPIO_PIN_4)
#define DCMI_D5_PIN (GPIO_PIN_5)
#define DCMI_D6_PIN (GPIO_PIN_6)
#define DCMI_D7_PIN (GPIO_PIN_6)

#define DCMI_D0_PORT (GPIOC)
#define DCMI_D1_PORT (GPIOC)
#define DCMI_D2_PORT (GPIOE)
#define DCMI_D3_PORT (GPIOE)
#define DCMI_D4_PORT (GPIOE)
#define DCMI_D5_PORT (GPIOE)
#define DCMI_D6_PORT (GPIOE)
#define DCMI_D7_PORT (GPIOB)

#define DCMI_HSYNC_PIN (GPIO_PIN_7)
#define DCMI_VSYNC_PIN (GPIO_PIN_4)
#define DCMI_PXCLK_PIN (GPIO_PIN_6)

#define DCMI_HSYNC_PORT (GPIOB)
#define DCMI_VSYNC_PORT (GPIOA)
#define DCMI_PXCLK_PORT (GPIOA)

/* GPIO struct */
typedef struct {
    GPIO_TypeDef *port;
    uint16_t pin;
} gpio_t;

/* DCMI GPIOs */
static const gpio_t dcmi_pins[] = 
{
    {DCMI_D0_PORT, DCMI_D0_PIN},
    {DCMI_D1_PORT, DCMI_D1_PIN},
    {DCMI_D2_PORT, DCMI_D2_PIN},
    {DCMI_D3_PORT, DCMI_D3_PIN},
    {DCMI_D4_PORT, DCMI_D4_PIN},
    {DCMI_D5_PORT, DCMI_D5_PIN},
    {DCMI_D6_PORT, DCMI_D6_PIN},
    {DCMI_D7_PORT, DCMI_D7_PIN},
    {DCMI_HSYNC_PORT, DCMI_HSYNC_PIN},
    {DCMI_VSYNC_PORT, DCMI_VSYNC_PIN},
    {DCMI_PXCLK_PORT, DCMI_PXCLK_PIN},
};

#define NUM_DCMI_PINS   (sizeof(dcmi_pins)/sizeof(dcmi_pins[0]))

void HAL_DCMI_MspInit(DCMI_HandleTypeDef *hdcmi)
{
    /* DCMI clock enable */
    __DCMI_CLK_ENABLE();

    /* DCMI GPIOs configuration */
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.Pull = GPIO_PULLDOWN;
    GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
    GPIO_InitStructure.Alternate = GPIO_AF13_DCMI;

    /* Enable VSYNC EXTI */
    GPIO_InitStructure.Mode = GPIO_MODE_IT_RISING_FALLING;
    GPIO_InitStructure.Pin = DCMI_VSYNC_PIN;
    HAL_GPIO_Init(DCMI_VSYNC_PORT, &GPIO_InitStructure);

    /* Configure DCMI pins */
    GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
    for (int i = 0; i < NUM_DCMI_PINS; i++)
    {
        GPIO_InitStructure.Pin = dcmi_pins[i].pin;
        HAL_GPIO_Init(dcmi_pins[i].port, &GPIO_InitStructure);
    }
}
